package com.yunao.web.controller;

import com.yunao.commons.Exception.YunaoException;
import com.yunao.commons.constant.CookieConstant;
import com.yunao.commons.constant.RedisConstant;
import com.yunao.commons.enums.ResultEnum;
import com.yunao.commons.enums.UserTypeEnum;
import com.yunao.commons.utils.CookieUtil;
import com.yunao.commons.utils.JsonUtil;
import com.yunao.commons.utils.ResultVOUtil;
import com.yunao.commons.utils.VerifyUtil;
import com.yunao.commons.vo.ResultVO;
import com.yunao.entity.User;
import com.yunao.service.OrganizationService;
import com.yunao.service.TokenService;
import com.yunao.service.UserService;
import com.yunao.web.annotation.PassToken;
import com.yunao.web.annotation.UserLoginToken;
import com.yunao.web.form.LoginForm;
import com.yunao.web.utils.TokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.DigestUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.imageio.ImageIO;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.awt.image.BufferedImage;
import java.io.OutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;


@RestController
@Slf4j
@RequestMapping("/user")
@Scope("prototype")
public class LoginController {
    @Autowired
    private UserService userService;
    @Autowired
    private OrganizationService organService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    TokenService tokenService;

    @PassToken
    @RequestMapping("/login")
    public ResultVO login(@Valid LoginForm loginForm,
                          BindingResult bindingResult,
                          HttpServletRequest request,
                          HttpServletResponse response){
        if (bindingResult.hasErrors()){
            log.error("【用户登录】参数不正确");
            throw new YunaoException(ResultEnum.PARAM_ERROR.getCode(),
                    bindingResult.getFieldError().getDefaultMessage());
        }
        Map map = new HashMap();
        String username = loginForm.getUsername();
        String password = loginForm.getPassword();
        String code = loginForm.getCode();
        username=username.replace("@", ".");
        User user = userService.findByUsername(username);
        if (user==null){
            return ResultVOUtil.error(ResultEnum.USER_NOT_EXIST);
        }
        if (!DigestUtils.md5DigestAsHex(password.getBytes()).equals(user.getPassword())){
            return ResultVOUtil.error(ResultEnum.PASSWORD_ERROR);
        }
        HttpSession session = request.getSession();
        if(session.getAttribute("imageCode")==null ||!session.getAttribute("imageCode").toString().equalsIgnoreCase(code)){
            return ResultVOUtil.error(ResultEnum.CODE_ERROR);
        }
        Date organExpireDate = organService.findOne(user.getOrganId()).getOrganExpireDate();
        if (organExpireDate.before(new Date())){
            return ResultVOUtil.error(ResultEnum.ORGAN_OUT_DATE);
        }
        if(user.getExpireDate().before(new Date())){
            return ResultVOUtil.error(ResultEnum.ACCOUNT_OUT_DATE);
        }
        String token = tokenService.getToken(user);
        map.put("token",token);
        if (user.getRole()==UserTypeEnum.SYS_MANAGE.getCode())
            map.put("role",UserTypeEnum.SYS_MANAGE.getType());
        else if (user.getRole()==UserTypeEnum.ORGAN_MANAGE.getCode())
            map.put("role",UserTypeEnum.ORGAN_MANAGE.getType());
        else
            map.put("role",UserTypeEnum.COMMON_USER.getType());
        //redis设置key=UUID，value=user
//        rediskey = UUID.randomUUID().toString();
        String rediskey = String.format(RedisConstant.TOKEN_TEMPLATE,user.getUserId());
        Integer expire = CookieConstant.expire;
        stringRedisTemplate.opsForValue().set(rediskey,
                token,
                expire,
                TimeUnit.SECONDS);
        //cookie里设置token=rediskey
//        CookieUtil.set(response,CookieConstant.TOKEN,rediskey,CookieConstant.expire);
        user.setLastLoginTime(new Date());
        userService.save(user);
        session.setAttribute(CookieConstant.TOKEN,rediskey);
        return ResultVOUtil.success(map);
    }


    /**
     * 修改密码
     * @param oldpw   旧密码
     * @param newpw   新密码
     * @param conpw   确认密码
     * @return
     */
    @RequestMapping("/modifyPassword")
    public ResultVO modifyPassword(String oldpw,
                                   String newpw,
                                   String conpw,
                                   HttpServletRequest request){
        User user = TokenUtil.getTokenUser(userService);
        if (StringUtils.isEmpty(oldpw)){
            ResultVOUtil.error(99,"原密码不能为空");
        }
        if (StringUtils.isEmpty(newpw)){
            ResultVOUtil.error(100,"新密码不能为空");
        }
        if (StringUtils.isEmpty(conpw)){
            ResultVOUtil.error(101,"确认密码不能为空");
        }
        if (!DigestUtils.md5DigestAsHex(oldpw.getBytes()).equals(user.getPassword())){
            return ResultVOUtil.error(ResultEnum.PASSWORD_ERROR);
        }
        if (!newpw.equals(conpw)){
            return ResultVOUtil.error(102,"两次输入密码不同");
        }
        user.setPassword(DigestUtils.md5DigestAsHex(newpw.getBytes()));
        userService.save(user);

     /*   HttpSession session = request.getSession();
        String rediskey = (String) session.getAttribute(CookieConstant.TOKEN);
        stringRedisTemplate.delete(rediskey);
        session.removeAttribute(CookieConstant.TOKEN);*/
        return ResultVOUtil.success();
    }

    @PassToken
    @RequestMapping("/getToken")
    public ResultVO getToken(HttpServletRequest request){
        Map map = new HashMap<>();
//        Cookie cookie = CookieUtil.get(request,CookieConstant.TOKEN);
//        String rediskey = cookie.getValue();
        HttpSession session = request.getSession();
        String rediskey = (String) session.getAttribute(CookieConstant.TOKEN);
        if (rediskey==null||StringUtils.isEmpty(stringRedisTemplate.opsForValue().get(rediskey))){
            return ResultVOUtil.error(ResultEnum.TOKEN_ERROR);
        }
        Long expire = stringRedisTemplate.getExpire(rediskey,TimeUnit.SECONDS);
        String token = stringRedisTemplate.opsForValue().get(rediskey);
        map.put("token",token);
        map.put("expire",expire);
        return ResultVOUtil.success(map);
    }

    @RequestMapping("/logout")
    @UserLoginToken
    public ResultVO logout(HttpServletRequest request){
//        Cookie cookie = CookieUtil.get(request,CookieConstant.TOKEN);
//        String rediskey = cookie.getValue();
//        cookie.setMaxAge(0);
//        cookie.setPath("/");
        HttpSession session = request.getSession();
        String rediskey = (String) session.getAttribute(CookieConstant.TOKEN);
        stringRedisTemplate.delete(rediskey);
        session.removeAttribute(CookieConstant.TOKEN);
        return ResultVOUtil.success();
    }


    @PassToken
    @GetMapping("/getcode")
    public void getCode(HttpServletResponse response, HttpServletRequest request) throws Exception{
        HttpSession session=request.getSession();
        //利用图片工具生成图片
        //第一个参数是生成的验证码，第二个参数是生成的图片
        Object[] objs = VerifyUtil.createImage();
        //将验证码存入Session
        session.setAttribute("imageCode",objs[0]);

        //将图片输出给浏览器
        BufferedImage image = (BufferedImage) objs[1];
        response.setContentType("image/png");
        OutputStream os = response.getOutputStream();
        ImageIO.write(image, "png", os);
    }


}
